home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Maclife 157
/
MACLIFE157-2001-09.ISO.7z
/
MACLIFE157-2001-09.ISO
/
Linux
/
MacOS Tools
/
Other
/
BootX 1.1.3 (for Old Mac OS)
/
Sources
/
src
/
DeviceTree.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-07-23
|
7KB
|
279 lines
#include <MacTypes.h>
#include <stdlib.h>
#include <string.h>
#include "DeviceTree.h"
// Globals
int device_tree_skip_macos = 1;
int device_tree_max_prop_length = 1024;
// Statics
static RegEntryID gEntryID;
static struct device_node* gAllNodes;
static struct device_node** gAllNextP;
static Ptr gRegistryBase;
static char* gCurRegPath;
// Prototypes
static Ptr inspect_node( struct device_node *dad, Ptr where );
static unsigned char * get_property( struct device_node *np, const char *name, unsigned long *lenp);
static void relocate_node( struct device_node *np);
// Macros
#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
#define RELOC(x) ((x) ? (((Ptr)(x)) - gRegistryBase) : NULL)
// Exported copy_device_tree routine
OSStatus
copy_device_tree(Ptr where, unsigned long *size, unsigned long *outMainDispOffset)
{
OSStatus err;
Boolean done = false;
Ptr end;
GDHandle mainDisplay;
AuxDCEHandle mainDispDCE;
/// By default, we don't know which one is the main display
*outMainDispOffset = 0;
// We get the device control entry of the main display
mainDisplay = GetMainDevice();
mainDispDCE = (AuxDCEHandle)GetDCtlEntry((**mainDisplay).gdRefNum);
// We get the root of the device tree inside the registry
err = RegistryEntryIDInit(&gEntryID);
if (err == noErr)
err = RegistryCStrEntryLookup(NULL, "Devices:device-tree", &gEntryID);
if (err != noErr)
return err;
if ((err == noErr) && !done)
{
struct device_node* node;
struct device_node* next_node;
// Iterate the registry & copy everything
gCurRegPath = NULL;
gRegistryBase = where;
*((long *)where) = 0;
where += 4;
gAllNextP = &gAllNodes;
end = inspect_node(NULL, where);
*gAllNextP = 0;
*size = end - where;
// -- This one gives an error with Spotlight. I still have to check if it's a real
// error or not, but in the meantime, let's disable it.
// RegistryEntryIDDispose(&gEntryID);
// Now, relocate it
node = gAllNodes;
while(node)
{
unsigned char* did;
unsigned long didLength;
// Get next node pointer before it is relocated
next_node = node->allnext;
// Check if this node is a display device and contains the magic "did" property
if (strcmp(node->type, "display") == 0)
{
did = get_property(node, "did", &didLength);
if (did && didLength == sizeof(unsigned long))
if (*((unsigned long *)did) == (**mainDispDCE).dCtlSlot)
*outMainDispOffset = (unsigned long)RELOC(node);
}
// Relocate the node
relocate_node(node);
// Go to next node
node = next_node;
}
} else
*size = 0;
return err;
}
// Internel inspect_node recursive routine
Ptr
inspect_node( struct device_node *dad, Ptr where )
{
OSStatus err = noErr;
// unsigned long l;
struct device_node *np;
struct property *pp, **prev_propp;
RegPropertyIter propIter;
Boolean done = false;
RegEntryID me;
RegEntryIter cookie;
char* saveRegPath = gCurRegPath;
np = ( struct device_node * ) where;
where += sizeof( struct device_node );
memset(np, 0, sizeof(struct device_node));
// np->node = node;
*gAllNextP = np;
gAllNextP = &np->allnext;
np->parent = dad;
if ( dad )
{
/* we temporarily use the `next' field as `last_child'. */
if (dad->next == 0)
dad->child = np;
else
dad->next->sibling = np;
dad->next = np;
}
/* get and store all properties */
prev_propp = &np->properties;
err = RegistryPropertyIterateCreate( &gEntryID, &propIter );
for (;;) {
pp = (struct property *) where;
pp->name = ( char * )( pp + 1 );
err = RegistryPropertyIterate( &propIter, (RegPropertyName *)pp->name, &done);
if ( err || done )
break;
// Skip MacOS driver property
if (device_tree_skip_macos && (strcmp(pp->name, "driver,AAPL,MacOS,PowerPC") == 0))
continue;
err = RegistryPropertyGetSize( &gEntryID, pp->name, ( unsigned long * )( &pp->length ) );
if (err != noErr)
continue;
// Should not happen, but...
if (pp->length < 0)
continue;
// Skip too large properties
if (device_tree_max_prop_length && (pp->length > device_tree_max_prop_length))
continue;
where = ( Ptr )ALIGN( ( unsigned long )pp->name + strlen( pp->name ) + 1 );
pp->value = ( unsigned char * ) where;
pp->length = -1;
err = RegistryPropertyGet( &gEntryID, pp->name, pp->value, ( unsigned long * )( &pp->length ) );
where = ( Ptr )ALIGN( ( unsigned long ) where + pp->length );
*prev_propp = pp;
prev_propp = &pp->next;
}
done = false;
err = RegistryPropertyIterateDispose( &propIter );
*prev_propp = 0;
np->name = ( char * )get_property(np, "name", 0);
np->type = ( char * )get_property(np, "device_type", 0);
/* get the node's full name */
np->full_name = ( char * ) where;
if (gCurRegPath == NULL)
strcpy(np->full_name, "/");
else
{
strcpy(np->full_name, gCurRegPath);
if (strlen(gCurRegPath) > 1)
strcat(np->full_name, "/");
strcat(np->full_name, np->name);
}
gCurRegPath = np->full_name;
where = ( Ptr )ALIGN( ( unsigned long ) where + strlen(np->full_name) + 1 );
/* Backup entry to me */
err = RegistryEntryIDInit(&me);
if (err != noErr)
return where;
err = RegistryEntryIDCopy(&gEntryID, &me);
if (err != noErr)
return where;
/* Iterate child nodes */
err = RegistryEntryIterateCreate(&cookie);
if (err == noErr)
err = RegistryEntryIterateSet(&cookie, &gEntryID);
if (err == noErr)
{
err = RegistryEntryIterate( &cookie, kRegIterChildren, &gEntryID, &done);
while ((err == noErr) && !done)
{
where = inspect_node( np, where );
err = RegistryEntryIterate( &cookie, kRegIterContinue, &gEntryID, &done );
}
RegistryEntryIterateDispose(&cookie);
}
// we got done, so we must reset the gEntryID
err = RegistryEntryIDCopy(&me, &gEntryID);
if (err != noErr)
return where;
RegistryEntryIDDispose(&me);
gCurRegPath = saveRegPath;
return where;
}
unsigned char *
get_property( struct device_node *np, const char *name, unsigned long *lenp)
{
struct property *pp;
for ( pp = np->properties; pp != 0; pp = pp->next )
if ( strcmp( pp->name, (char *)name ) == 0 ) {
if ( lenp != 0 )
*lenp = pp->length;
return pp->value;
}
return nil;
}
void
relocate_node(struct device_node *np)
{
struct property* prop;
struct property* prop_next;
prop = np->properties;
np->name = (char *)RELOC(np->name);
np->type = (char *)RELOC(np->type);
np->node = NULL;
np->addrs = NULL;
np->full_name = (char *)RELOC(np->full_name);
np->properties = (struct property *)RELOC(np->properties);
np->parent = (struct device_node *)RELOC(np->parent);
np->child = (struct device_node *)RELOC(np->child);
np->sibling = (struct device_node *)RELOC(np->sibling);
np->next = (struct device_node *)RELOC(np->next);
np->allnext = (struct device_node *)RELOC(np->allnext);
while(prop)
{
prop_next = prop->next;
prop->name = (char *)RELOC(prop->name);
prop->value = (unsigned char *)RELOC(prop->value);
prop->next = (struct property *)RELOC(prop->next);
prop = prop_next;
}
}